﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using ParticleSystem;

namespace BGSpaceShooter
{
    public class StarFighterDrawer : GameObjectDrawer
    {
        private StarFighter starFighter;

        VertexBuffer treeVertexBuffer;
        VertexDeclaration treeVertexDeclaration;

        public StarFighterDrawer(StarFighter starFighter)
        {
            this.starFighter = starFighter;
        }

        public override void Draw(Camera camera)
        {
            Matrix modelMatrix = starFighter.ModelMatrix;
            Display.GraphicsDevice.RasterizerState = RasterizerState.CullNone;
            Display.GraphicsDevice.BlendState = BlendState.Opaque;
            Display.GraphicsDevice.DepthStencilState = DepthStencilState.Default;
            
            int i = 0;
            foreach (var model in starFighter.Model.Meshes)
            {
                foreach (Effect effect in model.Effects)
                {
                    //Macierze
                    effect.Parameters["xWorld"].SetValue(modelMatrix);
                    effect.Parameters["xView"].SetValue(camera.CameraMatrix);
                    effect.Parameters["xProjection"].SetValue(Display.ProjectionMatrix);

                    effect.Parameters["xEnableLighting"].SetValue(true);
                    effect.Parameters["xLightDirection"].SetValue(new Vector3(0, 0, 1));
                    effect.Parameters["xCameraPosition"].SetValue(camera.CameraPosition);

                    effect.Parameters["xHasTexture"].SetValue(true);
                    effect.Parameters["xAmbient"].SetValue(starFighter.Ambient[i]);
                    effect.Parameters["xSpecularFactor"].SetValue(starFighter.SpecularFactor[i]);

                    effect.Parameters["xTexture"].SetValue(starFighter.Textures[i++]);
                }
                model.Draw();
            }
        }

        public override IEnumerable<ParticleSystem.EffectDrawer> GetEffectDrawers()
        {
            var effectDrawers = from effect in starFighter.GetEffectsToDraw() select effect.GetDrawer();
            var componentDrawers = from component in starFighter.StarFighterComponents select component.GetEffects();
            var effectsInComponents = componentDrawers.Aggregate((working, next) => working.Concat(next));
            var effectDrawersInComponents = from effect in effectsInComponents select effect.GetDrawer();
            return effectDrawers.Concat(effectDrawersInComponents).ToList();
        }

        private void DrawBillboards(Camera camera)
        {
            Effect bbEffect = TechniqueProvider.GetEffect("Billboard");
            bbEffect.CurrentTechnique = bbEffect.Techniques["CylBillboard"];
            bbEffect.Parameters["xWorld"].SetValue(Matrix.Identity);
            bbEffect.Parameters["xView"].SetValue(camera.CameraMatrix);
            bbEffect.Parameters["xProjection"].SetValue(Display.ProjectionMatrix);
            bbEffect.Parameters["xCamPos"].SetValue(camera.CameraPosition);
            bbEffect.Parameters["xAllowedRotDir"].SetValue(new Vector3(0, 1, 0));
            bbEffect.Parameters["xBillboardTexture"].SetValue(GameContentManager.Content.GetTexture("RadarBG"));

            GraphicsDevice device = Display.GraphicsDevice;
            device.BlendState = BlendState.AlphaBlend;
            foreach (EffectPass pass in bbEffect.CurrentTechnique.Passes)
            {
                pass.Apply();
                device.SetVertexBuffer(treeVertexBuffer);
                int noVertices = treeVertexBuffer.VertexCount;
                int noTriangles = noVertices / 3;
                device.DrawPrimitives(PrimitiveType.TriangleList, 0, noTriangles);
            }
            device.BlendState = BlendState.Opaque;
        }

        private void CreateBillboardVerticesFromList(List<Vector3> treeList)
        {
            VertexPositionTexture[] billboardVertices = new VertexPositionTexture[treeList.Count * 6];
            int i = 0;
            foreach (Vector3 currentV3 in treeList)
            {
                billboardVertices[i++] = new VertexPositionTexture(currentV3, new Vector2(0, 0));
                billboardVertices[i++] = new VertexPositionTexture(currentV3, new Vector2(1, 0));
                billboardVertices[i++] = new VertexPositionTexture(currentV3, new Vector2(1, 1));

                billboardVertices[i++] = new VertexPositionTexture(currentV3, new Vector2(0, 0));
                billboardVertices[i++] = new VertexPositionTexture(currentV3, new Vector2(1, 1));
                billboardVertices[i++] = new VertexPositionTexture(currentV3, new Vector2(0, 1));
            }

            VertexDeclaration vertexDeclaration = VertexPositionTexture.VertexDeclaration;

            treeVertexBuffer = new VertexBuffer(Display.GraphicsDevice, vertexDeclaration, billboardVertices.Length, BufferUsage.WriteOnly);
            treeVertexBuffer.SetData(billboardVertices);
            treeVertexDeclaration = vertexDeclaration;
        }
    }
}
